﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace Sonce.Database
{
	public partial class DataViewer : UserControl
	{
		#region Members
		private bool aso = false; //Avoid StackOverflow
		private object dataContext = null;
		private IEnumerable allItems = null;
		#endregion

		#region Constructor
		/// <summary>
		/// Initializes a new DataViewer instance.
		/// </summary>
		public DataViewer()
		{
			InitializeComponent();
		}
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets a data repository class.
		/// </summary>
		/// <remarks>
		/// Properties in a class are indentified as tables. Thus the Tables ComboBox is populated with found property names.
		/// </remarks>
		public new object DataContext
		{
			get
			{
				return this.dataContext;
			}
			set
			{
				this.dataContext = value;
				if (this.dataContext != null)
				{
					Type type = this.dataContext.GetType();
					PropertyInfo[] properties = type.GetProperties();
					//cmbTables.ItemsSource = properties;

					cmbTables.Items.Clear();
					foreach (PropertyInfo property in properties)
					{
						cmbTables.Items.Add(new ComboBoxItem() { Content = property.Name });
					}
					cmbTables.SelectedIndex = 0;
				}
			}
		}

		/// <summary>
		/// Gets or sets items that are currently displayed in a grid.
		/// </summary>
		public IEnumerable ItemsSource
		{
			get
			{
				return this.allItems;
			}
			set
			{
				this.allItems = value;
				Refresh();
			}
		}

		/// <summary>
		/// Gets the current page number.
		/// </summary>
		public int PageNumber
		{
			get
			{
				int result = cmbPageNum.SelectedIndex + 1;
				return (result > 0 ? result : 1);
			}
		}

		/// <summary>
		/// Gets the total available items for the current table.
		/// </summary>
		public int ItemsCount
		{
			get
			{
				int count = 0;
				if (this.allItems != null)
				{
					foreach (var item in this.allItems)
					{
						count++;
					}
				}
				return count;
			}
		}

		/// <summary>
		/// Gets the maximum number of items that can be displayed per page.
		/// </summary>
		public int ItemsPerPage
		{
			get
			{
				int result = 0;
				if (cmbPageSize.SelectedItem != null)
				{
					ComboBoxItem item = cmbPageSize.SelectedItem as ComboBoxItem;
					int.TryParse(item.Content as string, out result);
				}
				return (result > 0 ? result : 25);
			}
		}
		#endregion

		#region Methods
		/// <summary>
		/// Refreshes a grid and ComboBoxes.
		/// </summary>
		public void Refresh()
		{
			if (this.aso)
			{
				return;
			}

			this.aso = true;

			if (this.allItems != null)
			{
				//var items = from x in this.allItems.OfType<IEnumerable<object>>() select x;
				//var items = this.allItems;

				//TODO: Find a better solution to get items
				List<object> items = new List<object>();
				foreach (var item in this.allItems)
				{
					items.Add(item);
				}

				var list = items.Skip(this.ItemsPerPage * (this.PageNumber - 1)).Take(this.ItemsPerPage);
				dgViewer.ItemsSource = null;
				dgViewer.ItemsSource = list;
			}

			if (cmbPageNum != null) //Skip while loading this UserControl
			{
				int count = (int)(this.ItemsCount / this.ItemsPerPage) + 1;
				List<int> pages = new List<int>();
				for (int i = 1; i <= count; i++)
				{
					pages.Add(i);
				}
				cmbPageNum.ItemsSource = pages;
				if (cmbPageNum.Items.Count > 0)
				{
					cmbPageNum.SelectedIndex = 0;
				}

				lblTotal.Text = this.ItemsCount.ToString();
			}

			this.aso = false;
		}
		#endregion

		#region Event handlers
		private void btnRefresh_Click(object sender, RoutedEventArgs e)
		{
			Refresh();
		}

		private void cmbTables_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			if (this.DataContext != null)
			{
				ComboBoxItem item = cmbTables.SelectedItem as ComboBoxItem;
				PropertyInfo property = this.DataContext.GetType().GetProperty(item.Content as string);
				MethodInfo method = property.GetGetMethod();
				object obj = method.Invoke(this.DataContext, null);
				if (obj is IEnumerable)
				{
					this.ItemsSource = null;
					this.ItemsSource = obj as IEnumerable;
				}
			}
		}

		private void cmbPageSize_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			Refresh();
		}

		private void cmbPageNum_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{
			Refresh();
		}
		#endregion
	}
}
